package com.deliinsns.sys.filter;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.deliinsns.sys.util.CookieUtils;
import com.deliinsns.sys.util.SystemConstant;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

@SuppressWarnings({"NullableProblems", "unchecked"})
public class AuthorizeFilter implements Filter {

	private String timeoutPage = "";
	private String errorPage = "";
	private String noAuthorizePage = "";
	private Set<String> ignoreUrlSet = new HashSet<String>();
	private Set<String> publicUrlSet = new HashSet<String>();
	private int expireTime = 3600 * 2;

	private Logger logger = LoggerFactory.getLogger(getClass());

	public void init(FilterConfig filterConfig) throws ServletException {
		String contextPath = filterConfig.getServletContext().getContextPath();
		this.timeoutPage = filterConfig.getInitParameter("timeoutPage");
		this.errorPage = filterConfig.getInitParameter("errorPage");
		String ignoreUrl = filterConfig.getInitParameter("ignoreUrl");
		Set<String> set1 = org.springframework.util.StringUtils.commaDelimitedListToSet(ignoreUrl);
		for (String url : set1) {
			url = url.trim();
			if (url.startsWith("/")) {
				ignoreUrlSet.add(contextPath + url);
			} else {
				ignoreUrlSet.add(contextPath + "/" + url);
			}
		}
		String publicUrl = filterConfig.getInitParameter("publicUrl");
		Set<String> set2 = org.springframework.util.StringUtils.commaDelimitedListToSet(publicUrl);
		for (String url : set2) {
			url = url.trim();
			if (url.startsWith("/")) {
				publicUrlSet.add(contextPath + url);
			} else {
				publicUrlSet.add(contextPath + "/" + url);
			}
		}
		//加上请求的默认页
		publicUrlSet.add(contextPath + "/");
		String expireTime = filterConfig.getInitParameter("expireTime");
		if (StringUtils.isNotBlank(expireTime)) {
			this.expireTime = Integer.valueOf(expireTime);
		}
	//	loginCache = (CacheFacade) ContextLoader.getCurrentWebApplicationContext().getBean("loginCache");
	}

	
	public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
		long reqStart = System.currentTimeMillis();
		HttpServletRequest request = (HttpServletRequest) servletRequest;
		HttpServletResponse response = (HttpServletResponse) servletResponse;
		String requestURI = request.getRequestURI();
		Map<String, String> userData = null;
		if (requestURI.contains("?")) {
			requestURI = requestURI.substring(0, requestURI.indexOf("?"));
		}
		try {
			//将系统配置的信息设置到request中
//			Map<String, String> configMap = systemConfig.getAllConfig();
//			if (configMap != null && !configMap.isEmpty()) {
//				for (Map.Entry<String, String> entry : configMap.entrySet()) {
//					String key = entry.getKey();
//					String value = entry.getValue();
//					servletRequest.setAttribute(key, value);
//					SystemContext.put(key, value);
//				}
//			}

			//如果是公用url，跳过session检测
			if (contains(publicUrlSet, requestURI)) {
				chain.doFilter(servletRequest, servletResponse);
				long reqEnd = System.currentTimeMillis();
				logger.info("request :" + requestURI + " cost:[" + (reqEnd - reqStart) + "] millseconds");
				return;
			}
			//登录检查
			//检查cookie
			String cookieId = CookieUtils.getCookieValue(request, SystemConstant.SESSION_ID);
//			if (StringUtils.isEmpty(cookieId) || !loginCache.exists(cookieId)) {
//				//如果是ajax请求，返回411状态
//				if (RequestUtils.isAjax(request)) {
//					response.setStatus(411);
//					return;
//				}
//				response.sendRedirect(request.getContextPath() + timeoutPage);
//				return;
//			}
//			userData = loginCache.getMap(cookieId);
//			loginCache.expireString(cookieId,expireTime);
//			userData.put(SystemConstant.CLIENT_IP, request.getRemoteAddr());
//			userData.put(SystemConstant.USER_AGENT, request.getHeader("User-Agent"));
//			userData.put(SystemConstant.REQUEST_URL, requestURI);
//			for (Map.Entry<String, String> entry : userData.entrySet()) {
//				SystemContext.put(entry.getKey(), entry.getValue());
//			}
			//TODO 做用户角色权限控制
			/*if (contains(ignoreUrlSet, requestURI)) {
				chain.doFilter(servletRequest, servletResponse);
				long reqEnd = System.currentTimeMillis();
				logger.info("request :" + requestURI + " cost:[" + (reqEnd - reqStart) + "] millseconds");
				return;
			}*/
			chain.doFilter(servletRequest, servletResponse);
			long reqEnd = System.currentTimeMillis();
			logger.info("request :" + requestURI + " cost:[" + (reqEnd - reqStart) + "] millseconds");
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
//			response.setStatus(506);
			response.sendRedirect(request.getContextPath() + errorPage);
			long reqEnd = System.currentTimeMillis();
			logger.info("request :" + requestURI + " cost:[" + (reqEnd - reqStart) + "] millseconds");
		} finally {
		//	request.setAttribute(SystemConstant.REQUEST_IS_AJAX, RequestUtils.isAjax(request));
			//清除系统的线程变量
		//	SystemContext.setContextMap(null);
			//清除消息 线程变量
			//先将消息保存到request中，然后清除线程变量
			//用户信息
			request.setAttribute("__userInfo", userData);
		}
	}

	
	public void destroy() {

	}

	/**
	 * 判断包含
	 *
	 * @param urlSet 授权url集合
	 * @param url    请求url
	 * @return 是否匹配
	 */
	private boolean contains(Set<String> urlSet, String url) {
		boolean falg = false;
		for (String s : urlSet) {
			if (wildcardMatch(s, url, "*")) {
				falg = true;
				break;
			}
		}
		return falg;
	}

	/**
	 * 通配符匹配
	 *
	 * @param pattern  模式
	 * @param str      字符
	 * @param wildcard 通配符
	 * @return 是否匹配
	 */
	public static boolean wildcardMatch(String pattern, String str, String wildcard) {
		if (StringUtils.isEmpty(pattern) || StringUtils.isEmpty(str)) {
			return false;
		}
		final boolean startWith = pattern.startsWith(wildcard);
		final boolean endWith = pattern.endsWith(wildcard);
		String[] array = StringUtils.split(pattern, wildcard);
		int currentIndex = -1;
		int lastIndex = -1;
		switch (array.length) {
			case 0:
				return true;
			case 1:
				currentIndex = str.indexOf(array[0]);
				if (startWith && endWith) {
					return currentIndex >= 0;
				}
				if (startWith) {
					return currentIndex + array[0].length() == str.length();
				}
				if (endWith) {
					return currentIndex == 0;
				}
				return str.equals(pattern);
			default:
				for (String part : array) {
					currentIndex = str.indexOf(part);
					if (currentIndex > lastIndex) {
						lastIndex = currentIndex;
						continue;
					}
					return false;
				}
				return true;
		}
	}

	private boolean checkLogin(HttpServletRequest request) {
		//检查cookie
		String cookieId = CookieUtils.getCookieValue(request, SystemConstant.SESSION_ID);
		if (StringUtils.isNotEmpty(cookieId)) {
		//	return loginCache.exists(cookieId);
		}
		return false;
	}
}
